package main

import (
	"fmt"
	"errors"
)
/*
将员工信息存入，然后通过id能迅速找到该员工的所有信息
要求：不能使用数据库，尽量节省内存，速度越快越好~   相当于===>哈希表完成
*/
func main(){
	var hashtable Hashtable
	var key string
	
	for {
		//调用哈希表的菜单列表
		fmt.Println("===雇员系统菜单===")
		fmt.Println("添加雇员请输入input")
		fmt.Println("显示雇员请输入show")
		fmt.Println("查找雇员请输入find")
		fmt.Println("删除雇员请输入delete")
		fmt.Println("退出系统请输入exit")
		fmt.Printf("请输入：")
		fmt.Scanln(&key)
		switch key{
			case "input" :
				var id int
				var name string
				fmt.Printf("请输入id：")
				fmt.Scanln(&id)
				fmt.Printf("请输入name：")
				fmt.Scanln(&name)
				emp := &Emp{
					Id : id,
					Name : name,
				}
				hashtable.Insert(emp)
			case "show" :
				hashtable.ShowAll()
			case "find" :
				var id int
				fmt.Printf("请输入你要查找的id:")
				fmt.Scanln(&id)
				emp := hashtable.FindById(id)
				if emp != nil{
					fmt.Println("雇员信息是： ",*emp)
				}else{
					fmt.Println("id的雇员不存在~")
				}
			case "delete":
				var id int
				fmt.Printf("请输入你要删除的id:")
				fmt.Scanln(&id)
				err := hashtable.DeleteById(id)
				if err != nil{
					fmt.Println("删除失败，原因：",err)
				}else{
					fmt.Println("删除成功！")
				}
			case "exit" :
				return
			default :
				fmt.Println("你输入指令无效，请重新输入")
		}
	}
}

//员工信息结构体------------------------------------------
type Emp struct{
	Id int
	Name string
	Next *Emp
}
//相应方法：




//指向链表的头  不带表头，第一个结点就是存放雇员--------------------------------------
type EmpLink struct{
	Head *Emp
}
//相应方法：
//添加员工的方法
func (this *EmpLink) Insert(emp *Emp){
	cur := this.Head  //辅助指针
	var pre *Emp = nil 
	//先判断当前链表是不是空链表
	if cur == nil{
		this.Head = emp
		return
	}
	if cur.Next == nil{
		if cur.Id > emp.Id{
			emp.Next = cur
			this.Head = emp
			return
		}
		
	}
	//若不是空链表，就开始找emp对应的位置插入，让cur与emp比较id，确保从小到大，并保持pre在cur前面
	for {
		if cur != nil{
			if cur.Id > emp.Id{
				break  //找到了位置
			}
			pre = cur  //保证前一个指针同步
			cur = cur.Next
		}else{
			break
		}
	}
	pre.Next = emp
	emp.Next = cur
}
//显示当前链表的信息
func (this *EmpLink)ShowLink(no int){
	if this.Head == nil{
		fmt.Printf("第%d链表为空~\n",no)
		return
	}
	//遍历当前链表所有结点
	cur := this.Head
	for{
		fmt.Printf(" [id:%d-Name:%s] -> ",cur.Id,cur.Name)
		if cur.Next == nil{
			break
		}
		cur = cur.Next
	}
	fmt.Println()
}
//查找相应的雇员
func (this *EmpLink)FindById(id int)(emp *Emp){
	cur := this.Head
	for {
		if cur != nil && cur.Id == id{
			return cur
		}else if cur == nil{
			break
		}
		cur = cur.Next
	}
	return nil
}
func (this *EmpLink)DeleteById(id int){
	cur := this.Head
	var pre *Emp
	if this.Head.Id == id {
		this.Head = cur.Next
		return 
	}
	pre = cur
	cur = cur.Next
	for {
		if cur != nil && cur.Id == id{
			pre.Next = cur.Next
			return
		}else if cur == nil{
			break
		}
		pre = cur
		cur = cur.Next
	}

}


//哈希表 是一个含有链表的数组-----------------------------------
type Hashtable struct{
	LinkArr [7]EmpLink
}
//相应方法：
func (this *Hashtable)Insert(emp *Emp){
	//使用散列函数确定该员工添加到哪个链表
	linkNo := this.HashFunc(emp.Id)
	//使用对应的链表添加
	this.LinkArr[linkNo].Insert(emp)
}
//散列函数，用于判断该雇员应该放在哪个链表
func (this *Hashtable)HashFunc(id int)int{  //使用id来判断
	return id % 7
}
//显示哈希table的所有雇员
func (this *Hashtable) ShowAll(){
	for i := 0;i < len(this.LinkArr);i++{
		this.LinkArr[i].ShowLink(i)
	}
}
//查找某id的数据
func (this *Hashtable)FindById(id int)(emp *Emp){
	linkNo := this.HashFunc(id)
	emp = this.LinkArr[linkNo].FindById(id)
	return emp
}
//删除某id的数据
func (this *Hashtable)DeleteById(id int)error{
	linkNo := this.HashFunc(id)
	emp := this.LinkArr[linkNo].FindById(id)
	if emp == nil{
		return errors.New("不存在该用户！")
	}
	this.LinkArr[linkNo].DeleteById(id)
	return nil
}